/*
 * sdmmc.h
 *
 *  Created on: Oct 16, 2013
 *      Author: Ken Arok
 */

#ifndef SDMMC_H_
#define SDMMC_H_

#include <stdint.h>
#include <stdbool.h>

/* This SD MMC stack uses the maximum block size authorized (512 bytes). */
#define SD_MMC_BLOCK_SIZE          512

/* \name Return error codes. */
//! @{
#define SD_MMC_OK               0    //! No error
#define SD_MMC_INIT_ONGOING     1    //! Card not initialized
#define SD_MMC_ERR_NO_CARD      2    //! No SD/MMC card inserted
#define SD_MMC_ERR_UNUSABLE     3    //! Unusable card
#define SD_MMC_ERR_SLOT         4    //! Slot unknown
#define SD_MMC_ERR_COMM         5    //! General communication error
#define SD_MMC_ERR_PARAM        6    //! Ilegal input parameter
#define SD_MMC_ERR_WP           7    //! Card write protected
#define SD_MMC_ERR_UNHANDLE		8	 //! Enhandle card type.
//! @}


/* \name Card Types. */
//! @{
#define CARD_TYPE_UNKNOWN   (0)      //!< Unknown type card
#define CARD_TYPE_SD        (1 << 0) //!< SD card
#define CARD_TYPE_MMC       (1 << 1) //!< MMC card
#define CARD_TYPE_SDIO      (1 << 2) //!< SDIO card
#define CARD_TYPE_HC        (1 << 3) //!< High capacity card
//! SD combo card (io + memory)
#define CARD_TYPE_SD_COMBO  (CARD_TYPE_SD | CARD_TYPE_SDIO)
//! @}

/* \name Card Versions. */
//! @{
#define CARD_VER_UNKNOWN   (0)       //! Unknown card version
#define CARD_VER_SD_1_0    (0x10)    //! SD version 1.0 and 1.01
#define CARD_VER_SD_1_10   (0x1A)    //! SD version 1.10
#define CARD_VER_SD_2_0    (0x20)    //! SD version 2.00
#define CARD_VER_SD_3_0    (0x30)    //! SD version 3.0X
#define CARD_VER_MMC_1_2   (0x12)    //! MMC version 1.2
#define CARD_VER_MMC_1_4   (0x14)    //! MMC version 1.4
#define CARD_VER_MMC_2_2   (0x22)    //! MMC version 2.2
#define CARD_VER_MMC_3     (0x30)    //! MMC version 3
#define CARD_VER_MMC_4     (0x40)    //! MMC version 4
//! @}

/* Type of return error code */
typedef uint8_t sdmmc_error_t;
/* Type of card type */
typedef uint8_t card_type_t;
/* Type of card version. */
typedef uint8_t card_version_t;
/* Card information. */

typedef struct {
	card_type_t type;
	card_version_t version;
	uint32_t capacity;
	uint32_t clock;
} card_info_t;


/** \brief Initialize SD/MMC Card.
 *
 * \return SD/MMC Status.
 */
extern sdmmc_error_t sdmmc_init(void);

/** \brief Check SD/MMC Card.
 *
 * \return SD/MMC Status.
 */
extern sdmmc_error_t sdmmc_check(void);

/** brief Get SD/MMC Card type.
 *
 * \return Card Type.
 */
extern card_type_t sdmmc_get_type(void);

/** \brief Get SD/MMC card version.
 *
 * \return Version of Card.
 */
extern card_version_t sdmmc_get_version(void);

/** \brief Get SD/MMC card capacity.
 *
 * \return Capacity of Card.
 */
extern uint32_t sdmmc_get_capacity(void);

/** \brief Get SD/MMC card information.
 *
 * \param Pointer to card info structure.
 */
extern void sdmmc_get_card_info(card_info_t *_card_info);

/** \brief Check if card is write protected.
 *
 * \return true if write protected. Unless false.
 */
extern bool sdmmc_is_write_protected(void);

/** \brief Initialize read block of data from card.
 *
 * \param _start		Start of block.
 * \param _nb_block		Number of block to be read.
 *
 * \return SD/MMC Status.
 */
extern sdmmc_error_t sdmmc_init_read_blocks(uint32_t _start, uint16_t _nb_block);

/** \brief Read block of data from card.
 *
 * \param _dest			Destination of buffer.
 * \param _nb_block		Number of block to be read.
 *
 * \return SD/MMC Status.
 */
extern sdmmc_error_t sdmmc_start_read_blocks(void *_dest, uint16_t _nb_block);

/** \brief Wait the end of reading block data.
 *
 * \return SD/MMC Status.
 */
extern sdmmc_error_t sdmmc_wait_end_of_read_blocks(void);

/** \brief Initialize write block of data to card.
 *
 * \param _start		Start of block.
 * \param _nb_block		Number of block to be written.
 *
 * \return SD/MMC Status.
 */
extern sdmmc_error_t sdmmc_init_write_blocks(uint32_t _start, uint16_t _nb_block);

/** \brief Write block of data to card.
 *
 * \param _dest			Source of buffer.
 * \param _nb_block		Number of block to be written.
 *
 * \return SD/MMC Status.
 */
extern sdmmc_error_t sdmmc_start_write_blocks(const void *_src, uint16_t _nb_block);

/** \brief Wait the end of writing block data.
 *
 * \return SD/MMC Status.
 */
extern sdmmc_error_t sdmmc_wait_end_of_write_blocks(void);

#endif /* SDMMC_H_ */
